package util;

import byggeTegner.DrawPanel;
import context.*;


import org.json.JSONObject;
import org.json.JSONException;

import util.ValueSpinner;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JComboBox;
import javax.swing.border.EmptyBorder;

// ********************************************************************
// *** CLASS: FontStyle
// ********************************************************************
public class FontStyle extends ValueType implements Context.Constants
{ //private static final boolean DEBUG=true; // Overriding Context.Constants.DEBUG
  static final String TAG="util.FontStyle";

  public static final String DEFAULT_FONT_FAMILY="Arial"; // Depends on user agent
  public static final int DEFAULT_FONT_STYLE=Style.plain; // plain | italic | bold | boldItalic
  public static final int DEFAULT_FONT_SIZE=10;//12; //
  
  public static final FontStyle defaultStyle=new FontStyle(DEFAULT_FONT_FAMILY,DEFAULT_FONT_STYLE,DEFAULT_FONT_SIZE);
  public static final Font defaultFont=new Font(DEFAULT_FONT_FAMILY,Font.PLAIN,DEFAULT_FONT_SIZE);
  public static final Font rammeFont=defaultFont;//new Font("Arial",Font.BOLD,9);//7);
  public static final Font titleBorderFont=new Font("Dialog",Font.BOLD,12);
  
  public interface Style
  { public static final int plain=0;
	public static final int italic=1;  
	public static final int bold=2;  
	public static final int boldItalic=3;  
  }

  public static String encodeFontStyle(int style)
  { switch(style)
	{ case Style.plain: return("plain");
	  case Style.italic: return("italic");
	  case Style.bold:   return("bold");
	  case Style.boldItalic: return("boldItalic");
	}  
    throw(new IllegalArgumentException("style "+style));
  }

  public static int fontStyle(String style)
  { if(style.equalsIgnoreCase("plain"))  return(Style.plain);
    if(style.equalsIgnoreCase("italic")) return(Style.italic);
    if(style.equalsIgnoreCase("bold"))   return(Style.bold);
    if(style.equalsIgnoreCase("boldItalic")) return(Style.boldItalic);
    throw(new IllegalArgumentException("style "+style));
  }
  private String FONT_FAMILY=DEFAULT_FONT_FAMILY;
  private int FONT_STYLE=DEFAULT_FONT_STYLE;
  private double FONT_SIZE=DEFAULT_FONT_SIZE;
  
  public String getFontFamily() { return(FONT_FAMILY); }
  public int getFontStyle() { return(FONT_STYLE); }
  public double getFontSize() { return(FONT_SIZE); }
  
  public void setFontFamily(String newFamily)
  { if(!FONT_FAMILY.equalsIgnoreCase(newFamily)) { FONT_FAMILY=newFamily; FIRE_CHANGE_EVENT("FONT_FAMILY"); } }
  public void setFontStyle(int newStyle) { if(FONT_STYLE!=newStyle) { FONT_STYLE=newStyle; FIRE_CHANGE_EVENT("FONT_STYLE"); } }
  public void setFontSize(double newSize) { if(FONT_SIZE!=newSize) { FONT_SIZE=newSize; FIRE_CHANGE_EVENT("FONT_SIZE"); } }
  
  // *************************************************************************
  // *** CONSTRUCTOR: FontStyle
  // *************************************************************************
  public FontStyle(String fontFamily,int fontStyle,double fontSize)
  { FONT_FAMILY=fontFamily;
    FONT_STYLE=fontStyle;
    FONT_SIZE=fontSize;
  }

  public FontStyle()
  { EditorProperties.loadFont(this); }
  
  public FontStyle(JSONObject parent) throws JSONException
  { JSONObject obj=parent.optJSONObject("font");
    if(obj!=null)
    { String atr=obj.optString("family"); if(atr.length()!=0) setFontFamily(atr);
      atr=obj.optString("style"); if(atr.length()!=0) setFontStyle(fontStyle(atr));
      atr=obj.optString("size"); if(atr.length()!=0) setFontSize(Double.parseDouble(atr));
    }
  }

  public JSONObject encode() throws JSONException
  {	JSONObject obj=new JSONObject();
   	obj.put("family",getFontFamily());
	if(getFontStyle()!=DEFAULT_FONT_STYLE) obj.put("style",encodeFontStyle(getFontStyle()));
	if(getFontSize()!=DEFAULT_FONT_SIZE) obj.put("size",getFontSize());
	return(obj);
  }
  
  public Font getUnZoomedFont() { return(getFont(null)); }
  public Font getFont(DrawPanel drawPanel)
//  public Font getFont()
  { int style=Font.PLAIN;
    switch(getFontStyle())
    { case Style.plain:      style=Font.PLAIN; break;
      case Style.italic:     style=Font.ITALIC; break;
      case Style.bold:       style=Font.PLAIN|Font.BOLD; break;
      case Style.boldItalic: style=Font.ITALIC|Font.BOLD; break;
    }
	Font font=new Font(getFontFamily(),style,(int)getFontSize());  
    if(drawPanel!=null)	font=font.deriveFont((float)(font.getSize2D()/drawPanel.getPixelsPerScaledMeter()));
//    if(drawPanel!=null)	font=font.deriveFont((float)(font.getSize2D()/drawPanel.getPrintScale()));
	return(font);  
  }
  
  public void setFont(String family,int style,int size)
  { setFontFamily(family);
	setFontStyle(style);
	setFontSize(size);
  }

  public FontStyle copy()
  { FontStyle font=new FontStyle();
    copy(this,font);
	return(font);  
  }

  public static void copy(FontStyle from,FontStyle to)
  { to.setFontFamily(from.getFontFamily());
    to.setFontStyle(from.getFontStyle());
    to.setFontSize(from.getFontSize());
  }

  //********************************************************************
  //*** UTILITY: editFont
  //********************************************************************
  public static String editFont(Graphics2D g)
  { double scale=g.getTransform().getScaleX();
    String name=g.getFont().getFamily();
    float size2D=g.getFont().getSize2D();
    int size=(int)(size2D*scale+0.5);
    return("Font: "+name+", size="+size+", size2D="+size2D+", Scale="+scale);
  }
  
  //********************************************************************
  //*** INNER CLASS: FontDialog
  //********************************************************************
  public class FontDialog extends EditValueTypeDialog
  { static final long serialVersionUID=0; // AD'HOC
    private JButton okBtn;
    private JButton cancelBtn;
    // Initial Values:
    private FontStyle initialFont;
    protected void saveInitialValues()
    { initialFont=FontStyle.this.copy(); }
    protected void restoreInitialValues()
    { copy(initialFont,FontStyle.this); }
    // ******************************************************************
    // *** CONSTRUCTOR: FontDialog
    // ******************************************************************
    public FontDialog(final StrokeStyle stroke,final boolean saveToProperties)
    { super(FontStyle.this,"Edit Font Attributes");
      setExtraListener1On(stroke);
      setBounds(300,200,445,270); // Popup to: x,y,width,height
      JPanel buttons=new JPanel();
      buttons.add(okBtn=new JButton("Ok"));
      okBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { if(saveToProperties) EditorProperties.storeFont(FontStyle.this);
          close();
        }
      });
      buttons.add(cancelBtn=new JButton("Cancel"));
      cancelBtn.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e) { cancel(); } });
      setLayout(new BorderLayout());
      add(new FontAttributesPanel("Font"),BorderLayout.NORTH);
      add(new FontPreViewPanel(stroke),BorderLayout.CENTER);
      add(buttons,BorderLayout.SOUTH);
      setAlwaysOnTop(true);
      setVisible(true);
    }
  }
  

  // ****************************************************************
  // *** INNER CLASS: FontAttributesPanel
  // ****************************************************************
  private class FontAttributesPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC

    public FontAttributesPanel(String title)
    { setBorder(Util2.getTitleBorder(title));
      setPreferredSize(new Dimension(350,90));
      setLayout(new GridLayout(3,2));
      
      add(new JLabel("Font Family:"));
      { 
    	String[] vals=GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        final JComboBox comboBox1=new JComboBox(vals);
        LOOP:for(int i=0;i<vals.length;i++)
        { if(DEBUG) Log.d(TAG,"FontAttributesPanel.CHECK: "+getFontFamily()+" MOT "+vals[i]);
          if(vals[i].equalsIgnoreCase(getFontFamily()))
          { comboBox1.setSelectedIndex(i);
        	break LOOP;
          }
        }
        comboBox1.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e)
          { String selected=(String)comboBox1.getSelectedItem();
      	    if(DEBUG) Log.d(TAG,"ACTION: "+comboBox1.getSelectedItem());
            setFontFamily(selected);
          }
        });
        add(comboBox1);
      }
      
      add(new JLabel("Font Size:"));
      add(new ValueSpinner(getFontSize(),1.0,40.0,1.0)
      { static final long serialVersionUID=0; // AD'HOC
        public void update(double value)
        { setFontSize((int)value); }	
      });
      
      add(new JLabel("Font Style:"));
      { String[] vals={"plain","italic","bold","bold italic"};
        final JComboBox comboBox=new JComboBox(vals);
        switch(getFontStyle())
        { case Style.plain: comboBox.setSelectedIndex(0); break;
          case Style.italic: comboBox.setSelectedIndex(1); break;
          case Style.bold:   comboBox.setSelectedIndex(2); break;
          case Style.boldItalic: comboBox.setSelectedIndex(3); break;
        }
        comboBox.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e)
          { String selected=(String)comboBox.getSelectedItem();
      	    if(DEBUG) Log.d(TAG,"ACTION: "+comboBox.getSelectedItem());
            if(selected.equalsIgnoreCase("plain")) setFontStyle(Style.plain);
            if(selected.equalsIgnoreCase("italic")) setFontStyle(Style.italic);
            if(selected.equalsIgnoreCase("bold")) setFontStyle(Style.bold);
            if(selected.equalsIgnoreCase("bold italic")) setFontStyle(Style.boldItalic);
          }
        });
        add(comboBox);
      }
    }
  }

  // ****************************************************************
  // *** INNER CLASS: FontPreViewPanel
  // ****************************************************************
  public class FontPreViewPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private StrokeStyle svgStroke;
    // **************************************************************
    // *** CONSTRUCTOR: FontPreViewPanel
    // **************************************************************
    public FontPreViewPanel(StrokeStyle svgStroke)
    { this.svgStroke=svgStroke;
      setBorder(new EmptyBorder(10,5,5,5));
      setPreferredSize(new Dimension(350,40));
    }

    public void paint(Graphics g)
    { super.paint(g);
      int w=getWidth(); int h=getHeight();
      Util2.fill((Graphics2D)g,new Rectangle2D.Double(10,20,w-20,h-30),Color.white);
	  Util2.drawString((Graphics2D)g,getFontFamily(),15,60,FontStyle.this.getUnZoomedFont(),svgStroke,null,1);
    }
  }

}
